package rpcserver

import (
	"context"
	"strconv"

	"regexp"

	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/x/errors"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

type Middleware struct {
	// Db    *chendb.ChenDb
	// Cache *redis.Redis
}

func NewMiddleware() *Middleware {
	return &Middleware{}
}

// rpc拦截器: 把rpc返回普通类型异常, 转为rpc异常
func (m Middleware) LoggerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
	resp, err = handler(ctx, req)
	if err != nil {
		logx.WithContext(ctx).Errorf("[rpc-err] %+v", err)
		switch e := err.(type) {
		case *errors.CodeMsg:
			err = status.Error(codes.Code(e.Code), e.Msg)
		default:
			err = status.Error(codes.Code(10000), e.Error())
		}
	}
	return resp, err
}

// rpc-client客户端拦截器(rpc返回数据到api时触发): 异常处理
func (m Middleware) ClientRpcMiddleware(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
	err := invoker(ctx, method, req, reply, cc, opts...)
	if err != nil {
		errStr := err.Error()
		reg := regexp.MustCompile(`code = Code\((?P<code>\d+)\) desc = (?P<msg>.*)`)
		res := reg.FindAllStringSubmatch(errStr, 1)
		for _, match := range res {
			codeStr := match[reg.SubexpIndex("code")]
			msg := match[reg.SubexpIndex("msg")]
			code, e := strconv.Atoi(codeStr)
			if e != nil {
				code = 9000
			}
			err = errors.New(code, msg)
		}
		return err
	}
	return nil
}

// 没用
func (m Middleware) AuthInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
	resp, err = handler(ctx, req)
	return resp, err
}
